<?php

/**
 * @package   yii2-export
 * @author    Kartik Visweswaran <kartikv2@gmail.com>
 * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2015 - 2017
 * @version   1.2.8
 */

namespace backend\components\exports;

use Closure;
use kartik\base\TranslationTrait;
use kartik\dialog\Dialog;
use kartik\dynagrid\Dynagrid;
use kartik\grid\GridView;
use kartik\mpdf\Pdf;
use PHPExcel;
use PHPExcel_IOFactory;
use PHPExcel_Style_Fill;
use PHPExcel_Worksheet;
use PHPExcel_Worksheet_PageSetup;
use PHPExcel_Writer_Abstract;
use PHPExcel_Writer_CSV;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\bootstrap\ButtonDropdown;
use yii\data\ActiveDataProvider;
use yii\data\BaseDataProvider;
use yii\db\ActiveQueryInterface;
use yii\grid\ActionColumn;
use yii\grid\Column;
use yii\grid\DataColumn;
use yii\grid\SerialColumn;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\web\JsExpression;
use yii\web\View;
use kartik\export\ExportMenu;
use common\models\c2\entity\SalesOrderItem;

/**
 * Export menu widget. Export tabular data to various formats using the PHPExcel library by reading data from a
 * dataProvider - with configuration very similar to a GridView.
 *
 * @author Kartik Visweswaran <kartikv2@gmail.com>
 * @since  1.0
 */
class CeExport extends ExportMenu
{

    public $groupByColIndex;
    public $autoWidth = false;
    public $_result;

    public function initPHPExcel()
    {
        $this->_objPHPExcel = new PHPExcel();
        $creator = $title = $subject = $category = $keywords = $manager = '';
        $description = Yii::t('app.c2', 'Grid export generated by Krajee ExportMenu widget (yii2-export)');
        $company = 'Krajee Solutions';
        $created = date('Y-m-d H:i:s');
        $lastModifiedBy = 'krajee';
        extract($this->docProperties);
        $properties = $this->_objPHPExcel->getProperties();
        $properties->setCreator($creator)
            ->setTitle($title)
            ->setSubject($subject)
            ->setDescription($description)
            ->setCategory($category)
            ->setKeywords($keywords)
            ->setManager($manager)
            ->setCompany($company)
            ->setCreated($created)
            ->setLastModifiedBy($lastModifiedBy);

        $this->_objPHPExcel->getDefaultStyle()
            ->getAlignment()
            ->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT)
            ->setVertical(\PHPExcel_Style_Alignment::VERTICAL_TOP);

        $this->raiseEvent('onInitExcel', [$this->_objPHPExcel, $this]);
    }

    public function generateBody()
    {
        $this->_endRow = 0;
        $columns = $this->getVisibleColumns();
        $models = array_values($this->_provider->getModels());
        if (count($columns) == 0) {
            $cell = $this->_objPHPExcelSheet->setCellValue('A1', $this->emptyText, true);
            $model = reset($models);
            $this->raiseEvent('onRenderDataCell', [$cell, $this->emptyText, $model, null, 0, $this]);
            return 0;
        }
        // do not execute multiple COUNT(*) queries
        $totalCount = $this->_provider->getTotalCount();
        $this->findGroupedColumn();
        while (count($models) > 0) {
            $keys = $this->_provider->getKeys();
            foreach ($models as $index => $model) {
                $key = $keys[$index];
                $this->generateRow($model, $key, $this->_endRow);
                $this->_endRow++;
                if ($index === $totalCount) {
                    //a little hack to generate last grouped footer
                    $this->checkGroupedRow($model, $models[0], $key, $this->_endRow);
                } elseif (isset($models[$index + 1])) {
                    $this->checkGroupedRow($model, $models[$index + 1], $key, $this->_endRow);
                }
                if (!is_null($this->_groupedRow)) {
                    $this->_endRow++;
                    $this->_objPHPExcelSheet->fromArray($this->_groupedRow, null, 'A' . ($this->_endRow + 1), true);
                    $cell = 'A' . ($this->_endRow + 1) . ':' . self::columnName(count($columns)) . ($this->_endRow + 1);
                    $this->_objPHPExcelSheet->getStyle($cell)->applyFromArray($this->groupedRowStyle);
                    $this->_groupedRow = null;
                }
            }

            /*
             *  Merge Group Cells
             *  Modified by Ben Bi <bennybi@qq.com>
             */
            // $this->scanTable($models, $totalCount)->mergeCells();

            if ($this->_provider->pagination) {
                $this->_provider->pagination->page++;
                $this->_provider->refresh();
                $this->_provider->setTotalCount($totalCount);
                $models = $this->_provider->getModels();
            } else {
                $models = [];
            }
        }

        // Set autofilter on
        //        $this->_objPHPExcelSheet->setAutoFilter(
        //                self::columnName(1) . $this->_beginRow . ':' . self::columnName($this->_endCol) . $this->_endRow
        //        );

        foreach ($this->getVisibleColumns() as $n => $column) {
            $col = self::columnName($n + 1);
            $width = 20;
            switch ($col) {
                case "A":
                case "G":
                case "I":
                    $width = 30;
                    break;
                case "L":
                case "M":
                case "N":
                    $width = 8;
                    break;
                default:
                    break;
            }
            $this->_objPHPExcelSheet->getColumnDimension(self::columnName($n + 1))->setWidth($width);
        }

        return $this->_endRow;
    }


    protected function scanTable($models, $totalCount)
    {
        //查询需要合并的行
        $rows = $this->scanRows($models, $totalCount);
        //查询合并的列
        $cols = $this->scanCols();
        $this->_result = [
            'rows' => $rows,
            'cols' => $cols,
        ];
        return $this;
    }

    /*
     * 合并相同数据
     */
    protected function mergeCells()
    {
        foreach ($this->_result['rows'] as $row) {
            foreach ($this->_result['cols'] as $col) {
                $this->_objPHPExcelSheet->mergeCells($col . $row['start'] . ':' . $col . $row['end']);
            }
        }
    }

    protected function mergeGroupCells($model, $nextModel, $key, $index)
    {
        $endCol = 0;
        $rowOffset = $index + 1;
        foreach ($this->getVisibleColumns() as $k => $column) {
            /**
             * @var Column $column
             */
            $value = ($column->content === null) ? (method_exists($column, 'getDataCellValue') ?
                $this->formatter->format($column->getDataCellValue($model, $key, $index), 'raw') :
                $column->renderDataCell($model, $key, $index)) :
                call_user_func($column->content, $model, $key, $index, $column);


            if (is_null($nextModel)) {
                $nextValue = "";
            } else {
                $nextValue = ($column->content === null) ? (method_exists($column, 'getDataCellValue') ?
                    $this->formatter->format($column->getDataCellValue($nextModel, $key, $index), 'raw') :
                    $column->renderDataCell($nextModel, $key, $index)) :
                    call_user_func($column->content, $nextModel, $key, $index, $column);
            }

            if ($this->groupByColIndex == $k) {
                $orderId = $value;
                $nextOrderId = $nextValue;
            }

            //            Yii::info("endCol: {$endCol}, key:{$key}, index:{$index}, name:" . self::columnName($endCol + 1) . $rowOffset . " value:{$value}, nextValue:{$nextValue} ");
            if ((isset($this->_groupedColumn[$endCol])) && (!is_null($this->_groupedColumn[$endCol]))) {
                if (!empty($orderId) && ($orderId === $nextOrderId)) {
                    $groupedRange = self::columnName($endCol + 1) . $rowOffset . ':' . self::columnName($endCol + 1) . ($rowOffset + 1);
                    //                    Yii::info($groupedRange);
                    $this->_objPHPExcelSheet->mergeCells($groupedRange);
                }
            }
            $endCol++;
        }
    }

    protected function scanCols()
    {
        $cols = [];
        $visibleColumns = $this->getVisibleColumns();
        for ($i = 1; $i <= count($visibleColumns); $i++) {
            $col = self::columnName($i);
            if ($visibleColumns[$i - 1]->group == true) {
                $cols[] = $col;
            }
        }
        return $cols;
    }

    protected function scanRows($models, $totalCount)
    {
        $lastIndex = $totalCount - 1;
        $rows = [];
        $flag = true;
        for ($i = 0; $i < $lastIndex; $i++) {
            if ($flag == false) {
                break;
            }
            for ($j = $i; $j < $lastIndex; $j++) {
                if (!$models[$j + 1]) {
                    break;
                }
                if ($models[$j]->sales_order_id == $models[$j + 1]->sales_order_id) {
                    $rows[$i]['start'] = $i + 3;
                    $rows[$i]['end'] = $j + 3;
                    if ($j + 1 == $lastIndex) {
                        $flag = false;
                        break;
                    }
                } else {
                    $i = $j;
                }
            }
        }
        return $rows;
    }

}
